package com.kmxd.ams.app.search.command;

import cn.easyes.core.conditions.select.LambdaEsQueryWrapper;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.*;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import com.kmxd.ams.client.archive.*;
import com.kmxd.ams.client.es.IDocumentEsSvc;
import com.kmxd.ams.client.search.vo.SearchAuthVO;
import com.kmxd.ams.core.common.bo.ConditionBO;
import com.kmxd.ams.core.common.constant.ArchConst;
import com.kmxd.ams.core.common.constant.ErrorCode;
import com.kmxd.ams.core.common.constant.EsConst;
import com.kmxd.ams.core.common.enums.*;
import com.kmxd.ams.core.exception.BizTipException;
import com.kmxd.ams.core.util.SecurityUtil;
import com.kmxd.ams.infra.archive.entity.ArchiveAuthRule;
import com.kmxd.ams.infra.arrange.base.SystemBO;
import com.kmxd.ams.infra.search.entity.DocumentEs;
import java.util.*;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 特殊权限控制
 *
 * @author zuolg
 */
@Slf4j
@Component
@AllArgsConstructor
public class SpecialAuthCmd {
  private final IDocumentEsSvc documentEsSvc;
  private final IArchiveAuthRuleSvc archiveAuthRuleSvc;

  /**
   * 特殊权限获取
   *
   * @param archTypeId
   * @param systemBO
   * @param searchAuthVO
   */
  public void getSpecialAuth(Long archTypeId, SystemBO systemBO, SearchAuthVO searchAuthVO) {
    DocumentEs doc =
        Optional.ofNullable(documentEsSvc.getById(systemBO.getId(), systemBO.getTableId()))
            .orElseThrow(
                () -> BizTipException.instance(ErrorCode.USE_ARCH_DATA_NOT_FOUND, "未找到条目"));

    // 判断特殊权限设置是否有权限 zuolg 20231031
    if (ObjUtil.isEmpty(archTypeId)) {
      return;
    }
    // 权限设置
    Set<ArchiveAuthRule> conditions =
        archiveAuthRuleSvc.getAuthUseByUser(SecurityUtil.getLoginUser());
    // 过滤非当前档案门类数据
    List<ArchiveAuthRule> lists =
        conditions.stream()
            .filter(x -> ObjUtil.equal(x.getArchTypeId(), archTypeId))
            .collect(Collectors.toList());
    for (ArchiveAuthRule item : lists) {
      // 判断是否适用此规则
      if (checkDocAuthRule(doc, item)) {
        // 通用利用权限
        if (BooleanUtil.isTrue(item.getOnlineBrowser())
            || BooleanUtil.isTrue(searchAuthVO.getOnlineBrowser())) {
          searchAuthVO.setOnlineBrowser(true);
        }
        // 原文浏览
        if (BooleanUtil.isTrue(item.getBrowserFile())
            || BooleanUtil.isTrue(searchAuthVO.getBrowserFile())) {
          searchAuthVO.setBrowserFile(true);
        }
        if (BooleanUtil.isTrue(item.getOnlinePrint())
            || BooleanUtil.isTrue(searchAuthVO.getOnlinePrint())) {
          searchAuthVO.setOnlinePrint(true);
        }
        if (BooleanUtil.isTrue(item.getDownload())
            || BooleanUtil.isTrue(searchAuthVO.getDownload())) {
          searchAuthVO.setDownload(true);
        }

        if (BooleanUtil.isTrue(item.getDownloadSource())
            || BooleanUtil.isTrue(searchAuthVO.getDownloadSource())) {
          searchAuthVO.setDownloadSource(true);
        }
        if (BooleanUtil.isTrue(item.getLiveRead())
            || BooleanUtil.isTrue(searchAuthVO.getLiveRead())) {
          searchAuthVO.setLiveRead(true);
        }
        if (BooleanUtil.isTrue(item.getLendOut())
            || BooleanUtil.isTrue(searchAuthVO.getLendOut())) {
          searchAuthVO.setLendOut(true);
        }
        if (BooleanUtil.isTrue(item.getCopySend())
            || BooleanUtil.isTrue(searchAuthVO.getCopySend())) {
          searchAuthVO.setCopySend(true);
        }
        if (BooleanUtil.isTrue(item.getExcerpt())
            || BooleanUtil.isTrue(searchAuthVO.getExcerpt())) {
          searchAuthVO.setExcerpt(true);
        }
      }
    }
  }

  /**
   * 判断个人其他权限
   *
   * @param archTypeId
   * @param systemBO
   * @param useTypeEnum
   * @return
   */
  public boolean checkSpecialAuth(Long archTypeId, SystemBO systemBO, UseTypeEnum useTypeEnum) {
    DocumentEs doc =
        Optional.ofNullable(documentEsSvc.getById(systemBO.getId(), systemBO.getTableId()))
            .orElseThrow(
                () -> BizTipException.instance(ErrorCode.USE_ARCH_DATA_NOT_FOUND, "未找到条目"));
    // 判断特殊权限设置是否有权限 zuolg 20231031
    if (ObjUtil.isEmpty(archTypeId)) {
      return false;
    }
    // 权限设置
    Set<ArchiveAuthRule> conditions =
        archiveAuthRuleSvc.getAuthUseByUser(SecurityUtil.getLoginUser());
    // 过滤非当前档案门类数据
    List<ArchiveAuthRule> lists =
        conditions.stream()
            .filter(x -> ObjUtil.equal(x.getArchTypeId(), archTypeId))
            .collect(Collectors.toList());
    for (ArchiveAuthRule item : lists) {
      // 判断是否适用此规则
      if (checkDocAuthRule(doc, item)) {
        if (UseTypeEnum.ONLINE_BROWSER.equals(useTypeEnum)
            && BooleanUtil.isTrue(item.getOnlineBrowser())) {
          return true;
        }
        if (UseTypeEnum.BROWSER_FILE.equals(useTypeEnum)
            && BooleanUtil.isTrue(item.getBrowserFile())) {
          return true;
        }
        if (UseTypeEnum.ONLINE_PRINT.equals(useTypeEnum)
            && BooleanUtil.isTrue(item.getOnlinePrint())) {
          return true;
        }
        if (UseTypeEnum.DOWNLOAD.equals(useTypeEnum) && BooleanUtil.isTrue(item.getDownload())) {
          return true;
        }
        if (UseTypeEnum.DOWNLOAD_SOURCE.equals(useTypeEnum)
            && BooleanUtil.isTrue(item.getDownloadSource())) {
          return true;
        }
        if (UseTypeEnum.LIVE_READ.equals(useTypeEnum) && BooleanUtil.isTrue(item.getLiveRead())) {
          return true;
        }
        if (UseTypeEnum.LEND_OUT.equals(useTypeEnum) && BooleanUtil.isTrue(item.getLendOut())) {
          return true;
        }
        if (UseTypeEnum.COPY_SEND.equals(useTypeEnum) && BooleanUtil.isTrue(item.getCopySend())) {
          return true;
        }
      }
    }
    return false;
  }

  /**
   * 判断当前档案是否适用当前规则
   *
   * @param doc
   * @param rule
   */
  boolean checkDocAuthRule(DocumentEs doc, ArchiveAuthRule rule) {
    boolean flag = false;
    try {
      // 获取当前规则
      if (StrUtil.isNotBlank(rule.getRuleExpress()) && JSONUtil.isTypeJSON(rule.getRuleExpress())) {
        LambdaEsQueryWrapper<DocumentEs> wrapper = new LambdaEsQueryWrapper<>();
        wrapper.index(doc.getTableId());
        wrapper.eq(DocumentEs::getId, doc.getId());
        // 权限设置
        List<ConditionBO> conditions =
            Optional.ofNullable(JSONUtil.toList(rule.getRuleExpress(), ConditionBO.class))
                .orElse(Lists.newArrayList());
        wrapper.queryStringQuery(getQueryStr(conditions));
        List<DocumentEs> docs = documentEsSvc.list(wrapper);
        flag = !docs.isEmpty();
      }
    } catch (Exception e) {
      e.printStackTrace();
      log.info("特殊权限校验异常，不影响通用权限");
    }
    return flag;
  }

  /**
   * 获取特殊查询字符串
   *
   * @param conditions
   * @return
   */
  public static String getQueryStr(List<ConditionBO> conditions) {
    StringBuilder sb = new StringBuilder();
    // 最外层括号
    if (conditions.size() > 1) {
      sb.append("(");
    }
    for (ConditionBO item : conditions) {

      if (ObjectUtil.equals(item.getKey(), ArchConst.ARCH_CODE)
          || ObjectUtil.equals(item.getKey(), ArchConst.FIELD_TITLE)) {
        item.setKey(StrUtil.format("{}" + EsConst.FIELD_KEYWORD_SUFFIX, item.getKey()));
      }
      if (StrUtil.isNotBlank(item.getLogic())) {
        sb.append(item.getLogic().toUpperCase());

      } else {
        sb.append(" (");
        // 添加门类，表过滤
        if (ObjectUtil.isAllNotEmpty(item.getArchTypeId(), item.getTableId())) {
          sb.append(
              CharSequenceUtil.format(
                  "{}:{} AND {}:{} AND ",
                  ArchConst.TABLE_ID,
                  item.getTableId(),
                  ArchConst.ARCH_TYPE_ID,
                  item.getArchTypeId()));
        }

        if (ObjectUtil.isNotEmpty(item.getOperator())) {
          switch (item.getOperator()) {
              // 等于
            case EQ:
              sb.append(StrUtil.format("({}:{})", item.getKey(), item.getValue().trim()));
              break;
              // 不等于
            case NOT_EQ:
              sb.append(StrUtil.format("NOT({}:{})", item.getKey(), item.getValue().trim()));
              break;
              // 大于
            case GE:
              sb.append(StrUtil.format("GT({}:{})", item.getKey(), item.getValue().trim()));
              break;
              // 大于等于
            case GE_EQ:
              sb.append(StrUtil.format("GOE({}:{})", item.getKey(), item.getValue().trim()));
              break;
              // 小于
            case LE:
              sb.append(StrUtil.format("LT({}:{})", item.getKey(), item.getValue().trim()));
              break;
              // 小于等于
            case LE_EQ:
              sb.append(StrUtil.format("LOE({}:{})", item.getKey(), item.getValue().trim()));
              break;
              // 包含
            case LIKE:
              sb.append(StrUtil.format("({}:*{}*)", item.getKey(), item.getValue().trim()));
              break;
              // 不包含
            case NOT_LIKE:
              sb.append(StrUtil.format("NOT({}:*{}*)", item.getKey(), item.getValue().trim()));
              break;
              // 为空
            case EMPTY:
              sb.append(StrUtil.format("(NOT(_exists_:{}))", item.getKey()));
              break;
              // 不为空
            case NOT_EMPTY:
              sb.append(StrUtil.format("_exists_:{}", item.getKey()));
              break;
            default:
              break;
          }
        }
        sb.append(") ");
      }
    }
    if (conditions.size() > 1) {
      // 最外层括号
      sb.append(")");
    }
    return sb.toString();
  }
}
